#include <ArduinoJson.h>
#include <DHT.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#define DHTPIN 14        // DHT11传感器连接到数字引脚14 D5
#define RELAY_PIN 4     // 继电器连接到数字引脚4 D2

DHT dht(DHTPIN, DHT11);

const char* uid = "b3e9f9859d824a61ba36e63e1ea8f3ef"; // 替换成你的UID
const char* relayTopic = "JSQswitch006";
const char* relayTopic2 = "JSQhandswitch006";
const char* humidityTopic = "JSQhumidity004";
const char* temperatureTopic = "JSQtemperature004";  // 新增温度主题

const char* server = "bemfa.com";
const int port = 9501;  // 使用普通端口

// 定义WiFi网络列表（主备网络）
struct WiFiNetwork {
  const char* ssid;
  const char* password;
};

WiFiNetwork networks[] = {
  {"swku", "www.80.gd"},          // 主网络
  {"IT department", "0576123456"}, // 备用网络1
  // 可以继续添加更多备用网络
  // {"Backup_SSID", "Backup_PASSWORD"},
};
const int networkCount = sizeof(networks) / sizeof(networks[0]);
int currentNetworkIndex = 0; // 当前尝试的网络索引

WiFiClient espClient;
PubSubClient client(espClient);

bool switchState = false;
bool handswitchState = false;
unsigned long lastReconnectAttempt = 0;  // MQTT重连计时器
unsigned long lastWifiCheck = 0;         // WiFi检查计时器
unsigned long lastSensorRead = 0;        // 传感器读取计时器

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");

  // 将payload转换为String
  String receivedMessage = "";
  for (int i = 0; i < length; i++) {
    receivedMessage += (char)payload[i];
  }

  Serial.println(receivedMessage);

  if (strcmp(topic, relayTopic2) == 0) {
    // 如果是relay206主题的消息
    if (receivedMessage == "on") {
      // 手动开关，直接打开继电器
      digitalWrite(RELAY_PIN, HIGH);
      handswitchState = true;
      Serial.println("Relay HIGH (Manual ON)");
    } else if (receivedMessage == "off") {
      // 手动开关，直接关闭继电器
      digitalWrite(RELAY_PIN, LOW);
      handswitchState = false;
      Serial.println("Relay LOW (Manual OFF)");
    }
  }
  if (strcmp(topic, relayTopic) == 0) {
    // 如果是relay006主题的消息
    if (receivedMessage == "on") {
      switchState = true;
    } else {
      switchState = false;
    }
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW); // 确保继电器初始关闭
  dht.begin();

  // 初始连接WiFi
  connectToWiFi();

  // 设置MQTT服务器
  client.setServer(server, port);
  client.setCallback(callback);

  // 设置看门狗超时时间为60秒
  ESP.wdtEnable(60000000);
  Serial.println("Watchdog enabled (60s timeout)");
}

void connectToWiFi() {
  Serial.println();
  Serial.println("=== WiFi Connection ===");
  
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  
  int attempts = 0;
  
  while (true) {
    Serial.printf("Attempting to connect to: %s\n", networks[currentNetworkIndex].ssid);
    WiFi.begin(networks[currentNetworkIndex].ssid, networks[currentNetworkIndex].password);
    
    unsigned long startTime = millis();
    bool connected = false;
    
    while (millis() - startTime < 15000) { // 15秒连接超时
      if (WiFi.status() == WL_CONNECTED) {
        connected = true;
        break;
      }
      Serial.print(".");
      delay(500);
      yield(); // 喂狗
    }
    
    if (connected) {
      Serial.println("\nWiFi connected!");
      Serial.print("SSID: ");
      Serial.println(WiFi.SSID());
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
      lastReconnectAttempt = 0; // 重置MQTT连接计时器
      return;
    }
    
    Serial.println("\nConnection failed");
    
    // 切换到下一个网络
    currentNetworkIndex = (currentNetworkIndex + 1) % networkCount;
    attempts++;
    
    if (attempts >= networkCount * 2) { // 尝试所有网络两轮后稍作休息
      Serial.println("All networks failed, waiting before retry...");
      delay(5000);
      attempts = 0;
    }
  }
}

void reconnectMQTT() {
  Serial.println("Attempting MQTT connection...");
  
  if (client.connect(uid)) {
    Serial.println("Connected to MQTT server");
    client.subscribe(relayTopic);
    client.subscribe(relayTopic2);
    lastReconnectAttempt = 0; // 重置重连计时器
  } else {
    Serial.print("MQTT connection failed, rc=");
    Serial.print(client.state());
    Serial.println(" Retrying later...");
  }
}

void loop() {
  unsigned long currentMillis = millis();
  
  // 定期检查WiFi连接（每10秒）
  if (currentMillis - lastWifiCheck >= 10000) {
    lastWifiCheck = currentMillis;
    
    if (WiFi.status() != WL_CONNECTED) {
      Serial.println("WiFi connection lost! Reconnecting...");
      connectToWiFi();
    }
  }

  // MQTT连接管理
  if (!client.connected()) {
    // 每5秒尝试重连MQTT
    if (currentMillis - lastReconnectAttempt >= 5000) {
      lastReconnectAttempt = currentMillis;
      reconnectMQTT();
    }
  } else {
    client.loop();
  }

  // 每2秒读取一次传感器数据
  if (currentMillis - lastSensorRead >= 2000) {
    lastSensorRead = currentMillis;
    
    if (switchState) {
      // 读取湿度和温度值
      float humidity = dht.readHumidity();
      float temperature = dht.readTemperature();

      // 检查读取是否有效 - 修复语法错误
      if (isnan(humidity)) {
        humidity = -1;
      }
      if (isnan(temperature)) {
        temperature = -1;
      }

      // 打印湿度和温度值到串口监视器
      Serial.print("Humidity: ");
      Serial.print(humidity);
      Serial.println("%");
      Serial.print("Temperature: ");
      Serial.print(temperature);
      Serial.println("°C");

      // 检测温度并控制继电器 - 添加有效性检查
      if (temperature != -1) {
        if (temperature >= 38.0) {
          // 当温度大于等于38.0，给继电器输出一个高电平
          digitalWrite(RELAY_PIN, HIGH);
          Serial.println("Relay HIGH (Temperature)");
        } else if (temperature <= 32.0 && !handswitchState) {
          // 当温度小于等于32.0，给继电器输出一个低电平
          digitalWrite(RELAY_PIN, LOW);
          Serial.println("Relay LOW (Temperature)");
        }
      } else {
        Serial.println("Invalid temperature reading, skipping control");
      }

      // 发布湿度和温度到MQTT服务器
      if (client.connected()) {
        String humidityPayload = String(humidity);
        String temperaturePayload = String(temperature);
        client.publish(humidityTopic, humidityPayload.c_str());
        client.publish(temperatureTopic, temperaturePayload.c_str());
      }
    } else {
      // 巴法云返回"off"时，给继电器输出一个低电平
      if (!handswitchState) {
        digitalWrite(RELAY_PIN, LOW);
        Serial.println("Relay LOW (Switch off)");
      }
    }
  }

  delay(100);  // 短延时减少CPU负载
  yield();     // 喂狗 - 非常重要！
}